import React, { useEffect, useState, useRef } from "react";
import { SidebarStudent } from "../../../components/Sidebar";
import { GetFeedback, GetGrades, GetGradesAsg, GetQuestions, UpdateActive } from "../../../api";
import "./index.less";
import { GradingTask, Grade, GradeAsg, GradeChartYAxis, Question } from "../../../utils/constant";
import { useParams } from "react-router-dom";
import Chart from "react-apexcharts";
import { Form, FormInstance, Input, Modal, Select } from "antd";
const formRules = [{ required: true }];

const Index: React.FC = () => {
  const [feedback, setFeedback] = useState<GradingTask[]>([]);
  const [questions, setQuestions] = useState<Question[]>([]);
  const [grades, setGrades] = useState<Grade[]>([]);
  const [gradesAsg, setGradesAsg] = useState<GradeAsg[]>([]);
  const [isGradeModalOpen, setIsGradeModalOpen] = useState<boolean>(false);
  const [isCommentModalOpen, setIsCommentModalOpen] = useState<boolean>(false);
  const [isRequestModalOpen, setIsRequestModalOpen] = useState<boolean>(false);
  const formRef = useRef<FormInstance>(null);
  const params = useParams();
  const assignmentId = +params.assignmentId!;
  const [gradesChart, setGradesChart] = useState({
    options: {
      chart: {
        id: "scatter"
      },
      xaxis: {
        categories: ["Q1"]
      },
      markers: {
        size: [0],
        shape: ["circle"]
      }
    },
    series: [
      {
        name: "Reviewer 1",
        data: [0]
      }
    ]
  })
  const [xAxis, setXAxis] = useState([""]);
  const [yAxis, setYAxis] = useState<GradeChartYAxis[]>([]);
  const [markerSize, setMarkerSize] = useState<number[]>([]);
  const [markerShape, setMarkerShape] = useState<string[]>([]);

  const fetchFeedback = async () => {
    try {
      const { data } = (await GetFeedback(assignmentId));
      const res = data['data'];
      res.sort(function(a: GradingTask, b: GradingTask){
        // sort according to pairId in ascending order
        return a.pairId - b.pairId;
      });
      setFeedback(res);
    } catch (e) {
      console.error(e);
    }
  };

  const fetchQuestionList = async () => {
    try {
      const res = await GetQuestions({ assignmentId });
      const { code, msg } = res;
      if (code !== "00000") {
        throw new Error(msg);
      }
      setQuestions(res.data);
    } catch (e: any) {
      console.error(e);
    }
  };

  const fetchGrades = async (pairId: number) => {
    try {
      const { data } = await GetGrades(pairId);
      const res = data['data'];
      res.sort(function(a: Grade, b: Grade){
        // sort according to rubricId in ascending (question) order
        return a.rubricId - b.rubricId;
      });
      setGrades(res);
    } catch (e) {
      console.error(e);
    }
  }

  const fetchGradesAsg = async () => {
    try {
      const { data } = await GetGradesAsg(assignmentId);
      const res = data['data'];
      setGradesAsg(res);
    } catch (e) {
      console.error(e);
    }
  }

  const setGradesXAxis = async () => {
    const newCategories = [];
    for (let i = 0; i < questions.length; i++) {
      newCategories.push("Q" + (i+1) + " (max: " + questions[i].maxMark + ")");
    }
    setXAxis(newCategories);
  };

  const setGradesYAxis = async () => {
    // scatter plot of all data points
    const newSeries = [];
    let seriesData: number[] = [];
    const newSize = [];
    const newShape = [];
    let counter = 0;
    let reviewerCount = 1;
    for (let i = 0; i < gradesAsg.length; i++) {
      if (counter === questions.length) {
        if (seriesData.length != 0) {
          newSeries.push({name: "Reviewer " + reviewerCount, data: seriesData});
          newSize.push(6);
          newShape.push("circle");
          reviewerCount++;
          seriesData = [];
        }
        counter = 0;
      }
      // check if review for this pairId has been voided
      feedback.forEach((feedbackPair) => {
        if (feedbackPair.pairId === gradesAsg[i].pairingId) {
          if (feedbackPair.active != 2) { // not voided, include grade in chart
            seriesData.push(gradesAsg[i].grade);
          }
        }
      })
      counter++;
    }
    if (seriesData.length != 0) {
      newSeries.push({name: "Reviewer " + reviewerCount, data: seriesData});
      newSize.push(6);
      newShape.push("circle");
    }

    // average grades for each qn
    const averageData = []
    for (let i = 0; i < questions.length; i++) {
      let sumGrades = 0;
      for (let j = 0; j < newSeries.length; j++) {
        sumGrades = sumGrades + newSeries[j].data[i];
      }
      averageData.push(Math.round(sumGrades / newSeries.length * 10) / 10); // 1 d.p
    }
    newSeries.push({name: "Average", data: averageData});
    newSize.push(1);
    newShape.push("square");

    setYAxis(newSeries);
    setMarkerSize(newSize);
    setMarkerShape(newShape);
  }

  const openGradeModal = () => {
    setIsGradeModalOpen(true);
  };
  const closeGradeModal = () => {
    setIsGradeModalOpen(false);
  };
  const openCommentModal = () => {
    setIsCommentModalOpen(true);
  };
  const closeCommentModal = () => {
    setIsCommentModalOpen(false);
  };
  const openRequestModal = () => {
    setIsRequestModalOpen(true);
  }
  const submitRequestModal = async () => {
    if (formRef.current?.getFieldsValue().pairId == null) {
      alert("Please select a Pairing ID!");
      return;
    }
    if (formRef.current?.getFieldsValue().reason == null) {
      alert("Please type in a challenge reason!");
      return;
    }
    await UpdateActive(
      {
        "pairId": formRef.current?.getFieldsValue().pairId, 
        "reason": formRef.current?.getFieldsValue().reason
      },
      assignmentId,
      3 // pending challenge
    ); 
    setIsRequestModalOpen(false);
    fetchFeedback();
  }
  const closeRequestModal = () => {
    setIsRequestModalOpen(false);
  }

  useEffect(() => {
    fetchFeedback();
    fetchQuestionList();
    fetchGradesAsg();
  }, []);

  useEffect(() => {
    setGradesXAxis();
  }, [questions]);

  useEffect(() => {
    setGradesYAxis()
  }, [gradesAsg, feedback])

  useEffect(() => {
    setGradesChart({
      options: {
        chart: {
          id: "scatter"
        },
        xaxis: {
          categories: xAxis
        },
        markers: {
          size: markerSize,
          shape: markerShape
        }
      },
      series: yAxis
  })
  }, [xAxis, yAxis]);

  return (
    <>
      <SidebarStudent></SidebarStudent>
      <div className="feedback">
        <h4>Fellow mates who have reviewed your work:</h4>
        <button
          id="challenge-task-button"
          onClick={() => {
            openRequestModal();
          }}>Submit Challenge Request
        </button>

        <table id="task-table" >
          <thead>
            <tr>
              <th>Pairing ID</th>
              <th>Review</th>
              <th>Grade</th>
              <th>Comment</th>
              <th>Status</th>
            </tr>
          </thead>
          <tbody>
            {feedback.map((val, key) => {
              return (
                <tr key={key}>
                  <td>{val.pairId}</td>
                  <td>
                    <a href= {
                      "../../../pdfViewer.html?pdf_url=" +
                      "http://localhost:8080/grade/getSubmissionFile/" +
                      val.fileKey +
                      "&assignmentId=" +
                      val.assignmentId +
                      "&pairingId=" +
                      val.pairId +
                      "&submissionId=" +
                      val.submissionId}
                    >
                      <button id="review-task-button">View Review</button>
                    </a>
                  </td>
                  <td>
                    <button
                      id="grade-task-button"
                      onClick={() => {
                        fetchGrades(val.pairId);
                        openGradeModal();
                      }}>View Grades
                    </button>
                  </td>
                  <td>
                    <button
                      id="comment-task-button"
                      onClick={() => {
                        fetchGrades(val.pairId);
                        openCommentModal();
                      }}>View Comments
                    </button>
                  </td>
                  {
                  val.active === 3 ? ( // Pending Challenge
                    <td>Pending Challenge</td>
                  ) :
                  val.active === 2 ? ( // VOIDED
                    <td style={{color: "red"}}>VOIDED</td>
                  ) :
                  val.active === 1 ? ( // completed
                    <td>
                      <img src="/images/greentick.png" width="20"></img>
                    </td>
                  ) :
                  val.active === 0 ? ( // not completed
                    <td>Awaiting Review</td>
                  ) : (<td></td>)
                  }
                </tr>
              );
            })}
          </tbody>
        </table>
        
        <Modal
          title="View Grades"
          open={isGradeModalOpen}
          onOk={closeGradeModal}
          onCancel={closeGradeModal}
        >
          {grades.map((val, key) => {
            return (
              <div key={key}>
                <p>Q{key+1}: <b>{val.grade}</b> / {questions.at(key)?.maxMark}</p>
              </div>
            )
          })}
        </Modal>
        <Modal
          title="View Comments"
          open={isCommentModalOpen}
          onOk={closeCommentModal}
          onCancel={closeCommentModal}
        >
          {grades.map((val, key) => {
            return (
              <div key={key}>
                <p>Q{key+1}: {val.comment}</p>
              </div>
            )
          })}
        </Modal>
        <Modal
          title="Request review to be challenged"
          open={isRequestModalOpen}
          onOk={submitRequestModal}
          onCancel={closeRequestModal}
        >
          <Form ref={formRef}>
            <Form.Item required label="Pairing ID" name="pairId" rules={formRules}>
              <Select>
                {feedback.map((pair) => {
                  return (
                    <Select.Option key={pair.pairId}>{pair.pairId}</Select.Option>
                  )
                })}
              </Select>
            </Form.Item>
            <Form.Item required label="Challenge Reason" name="reason" rules={formRules}>
              <Input.TextArea></Input.TextArea>
            </Form.Item>
          </Form>
        </Modal>
        
        <div>
          <p>Consolidated Grade Statistics:</p>
        </div>
        <Chart
          // options={gradesChart.options}
          series={gradesChart.series}
          type="scatter"
          width="600"
        />
        
      </div>
    </>
  );
};

export default Index;
